package com.item.util;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.lang.StringUtils;

import com.base.exception.SystemException;
import com.base.util.DateUtil;
import com.base.util.JSONUtils;

public class BeanUtils {
	static {
		BeanConverter converter = new BeanConverter();

		ConvertUtils.register(converter, Date.class);

		ConvertUtils.register(converter, BigDecimal.class);

		ConvertUtils.register(converter, String.class);
	}

	public static <T> T convert(Object inObj, Class<T> clz) {
		return (T) new BeanConverter().convert(clz, inObj);
	}

	public static Map<String, Object> json2Map(String jsonStr) {
		Map paramMap = new HashMap();

		if ((!StringUtils.isEmpty(jsonStr)) && (!"{}".equals(jsonStr))) {
			paramMap = (Map) JSONUtils.deserialize(jsonStr, HashMap.class);

			for (Object key : paramMap.keySet()) {
				if ("null".equals(paramMap.get(key))) {
					paramMap.put(key, null);
				}
			}
		}

		return paramMap;
	}

	public static void copyProperties(Object srcObject, Object destObject) throws Exception {
		BeanUtils.copyProperties(destObject, srcObject);
	}

	public static boolean isSimpleObject(Object o) {
		return o == null ? false : ClassUtils.isSimpleClz(o.getClass());
	}

	public static void main(String[] args) throws Exception {
		System.out.println(String.valueOf(new BigDecimal("0.01")));
	}

	private static class BeanConverter implements Converter {
		public Object convert(Class type, Object value) {
			if (value == null)
				return null;
			if ((value.getClass().equals(type)) || (type.isAssignableFrom(value.getClass()))) {
				return value;
			}

			if (type.equals(String.class)) {
				if ((value instanceof Date)) {
					return DateUtil.dateToStr((Date) value, "yyyy-MM-dd HH:mm:ss");
				}
				return String.valueOf(value);
			}

			if (type.equals(Date.class)) {
				if ((value instanceof Long))
					return new Date(((Long) value).longValue());
				if ((value instanceof String)) {
					int lengthb = ((String) value).getBytes().length;
					try {
						if (lengthb == "yyyy.MM.dd".getBytes().length)
							return DateUtil.strToDate(value.toString(), "yyyy-MM-dd");
						if (lengthb == "yyyy-MM-dd HH:mm:ss".getBytes().length)
							return DateUtil.strToDate(String.valueOf(value), "yyyy-MM-dd HH:mm:ss");
						if (lengthb == "EEE MMM dd HH:mm:ss zzz yyyy".getBytes().length) {
							//XXX wish to add in DateUtil
							SimpleDateFormat sdf = new SimpleDateFormat( 
									"EEE MMM dd HH:mm:ss 'CST' yyyy", Locale.US); 
							return sdf.parse(String.valueOf(value));
						} 
						if (lengthb != 0)
							throw new SystemException("无法将对象" + value + "转化为" + type.getName() + "类型!");
						return null;
					} catch (Exception e) {
						throw new SystemException("类型转化出现异常:" + e);
					}
				}
			} else if (type.equals(BigDecimal.class)) {
				if (StringUtils.isBlank(String.valueOf(value)))
					return null;
				if (BeanUtils.isSimpleObject(value))
					return new BigDecimal(String.valueOf(value));
			} else if (type.equals(Long.class)) {
				if (BeanUtils.isSimpleObject(value))
					return new Long(String.valueOf(value));
			} else if (type.equals(Integer.class)) {
				if (BeanUtils.isSimpleObject(value)) {
					if (((value instanceof String)) && (StringUtils.isBlank((String) value))) {
						return null;
					}
					return new Integer(String.valueOf(value));
				}
			} else if (type.equals(Map.class)) {
				if (!BeanUtils.isSimpleObject(value)) {
					return bean2map(value);
				}

			} else if ((value instanceof Map)) {
				return map2bean((Map) value, type);
			}
			return null;
		}

		private Object map2bean(Map<String, Object> srcMap, Class type) {
			Map propertyMap = ClassUtils.getClassPropertyType(type);
//			System.out.println(propertyMap);
			Object destObject;
			try {
//				System.out.println(type.getCanonicalName());
				destObject = type.newInstance();
			} catch (Exception localException1) {
				throw new SystemException("转型时无法实例化" + type.getName());
			}
			
			for (Object propertyName : propertyMap.keySet()) {
				if ((!srcMap.containsKey(propertyName)) && (!srcMap.containsKey(((String)propertyName).toLowerCase())))
					continue;
				Object propertyValue = srcMap.containsKey(propertyName) ? srcMap.get(propertyName) : srcMap.get(((String)propertyName).toLowerCase());

				if (propertyValue == null)
					continue;
				propertyValue = BeanUtils.convert(propertyValue, (Class) propertyMap.get(propertyName));
				try {
					if (propertyValue != null)
						org.apache.commons.beanutils.BeanUtils.setProperty(destObject, (String) propertyName, propertyValue);
				} catch (Exception e) {
					throw new SystemException(e.getMessage());
				}

			}

			return destObject;
		}

		private Map<String, Object> bean2map(Object value) {
			Map result = new HashMap();
			Map propertyMap;
			try {
				propertyMap = org.apache.commons.beanutils.BeanUtils.describe(value);
			} catch (Exception e) {
				throw new SystemException(e.getMessage());
			}
			propertyMap.remove("class");

			for (Object propertyName : propertyMap.keySet()) {
				result.put(propertyName, propertyMap.get(propertyName));
			}

			return result;
		}
	}
}